//    Copyright (C) Kherty.  All rights reserved.
using System;
using OpenLS.Spreadsheet.Extensibility;

namespace OpenLS.Spreadsheet.StandardAddIn
{
    [AddInFunctions]
    [AllowStringToDateTimeConversion]
    [AllowDoubleToDateTimeConversion]
    public class DateFunctions
    {
        [AllowStringToIntConversionAttribute]
        public static object Date([AllowStringToDoubleConversion]int year, int month, int day)
        {
            if (year < 0 || month < 0 || day < 0)
                return Errors.ValueError;
            if (year <= 1899)
                year = 1900 + year;
            if (month > 12)
            {
                return Date(year + 1, month - 12, day);
            }
            if (day > DateTime.DaysInMonth(year, month))
                return new DateTime(year, month, 1).AddDays(day - 1);
            return new DateTime(year, month, day);
        }

        public static double DateValue([WorksheetContext]IWorksheet worksheet,  string date_text)
        {
            return worksheet.Workbook.DateTimeToDouble(DateTime.Parse(date_text));
        }

        public static int Day(DateTime serial_number)
        {
            return serial_number.Day;
        }

        public static int Days360(DateTime start_date, DateTime end_date, [Optional(false)] bool method)
        {
            Date360 start = new Date360(start_date, true);
            Date360 end = new Date360(end_date, method);
            return end - start;
        }

        public static double EDate([WorksheetContext]IWorksheet worksheet, DateTime start_date, int months)
        {
            return worksheet.Workbook.DateTimeToDouble(start_date.AddMonths(months));
        }

        public static double EOMonth([WorksheetContext]IWorksheet worksheet,  DateTime start_date, int months)
        {
            DateTime result = start_date.AddMonths(months);
            result =  new DateTime(result.Year, result.Month, DateTime.DaysInMonth(result.Year, result.Month));
            return worksheet.Workbook.DateTimeToDouble(result);
        }

        public static int Hour(DateTime serial_number)
        {
            return serial_number.Hour;
        }

        public static int Minute(DateTime serial_number)
        {
            return serial_number.Minute;
        }

        public static int Month(DateTime serial_number)
        {
            return serial_number.Month;
        }

        public static DateTime Now()
        {
            return DateTime.Now;
        }

        public static int Second(DateTime serial_number)
        {
            return serial_number.Second;
        }

        public static DateTime Time([WorksheetContext]IWorksheet worksheet, int hour, int minute, int second)
        {
            DateTime dt = worksheet.Workbook.DoubleToDateTime(0);
            return new DateTime(dt.Year, dt.Month, dt.Day, hour, minute, second);
        }

        public static double TimeValue([WorksheetContext]IWorksheet worksheet, string text)
        {
            DateTime dt = DateTime.Parse(text);
            double dbl = worksheet.Workbook.DateTimeToDouble(dt);
            return dbl - (int) dbl;
        }

        public static DateTime Today()
        {
            return DateTime.Today;
        }

        public static object WeekDay(DateTime serial_number, [Optional(1)] int return_type)
        {
            int d = (int) serial_number.DayOfWeek;
            switch (return_type)
            {
                case 1:
                case 2:
                    return (d - return_type + 9 - 1)%7 + 1;
                case 3:
                    return (d - return_type + 9)%7;
            }
            return Errors.NumError;
        }

        public static int Year(DateTime serial_number)
        {
            return serial_number.Year;
        }
    }
}